package cn.stylefeng.guns.modular.business.frequency.pricelibrary.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.stylefeng.guns.core.context.login.LoginContextHolder;
import cn.stylefeng.guns.core.exception.ServiceException;
import cn.stylefeng.guns.core.exception.enums.StatusExceptionEnum;
import cn.stylefeng.guns.core.factory.PageFactory;
import cn.stylefeng.guns.core.pojo.page.PageResult;
import cn.stylefeng.guns.modular.business.custom.enums.PriceLibraryStatusEnum;
import cn.stylefeng.guns.modular.business.custom.enums.PriceLibraryTypeEnum;
import cn.stylefeng.guns.modular.business.frequency.cmarea.mapper.CmAreaMapper;
import cn.stylefeng.guns.modular.business.frequency.cmcity.mapper.CmCityMapper;
import cn.stylefeng.guns.modular.business.frequency.pricelibrary.entity.PriceLibrary;
import cn.stylefeng.guns.modular.business.frequency.pricelibrary.enums.PriceLibraryExceptionEnum;
import cn.stylefeng.guns.modular.business.frequency.pricelibrary.listener.excel.PriceLibraryListener;
import cn.stylefeng.guns.modular.business.frequency.pricelibrary.mapper.PriceLibraryMapper;
import cn.stylefeng.guns.modular.business.frequency.pricelibrary.model.param.PriceLibraryDTO;
import cn.stylefeng.guns.modular.business.frequency.pricelibrary.model.param.PriceLibraryParam;
import cn.stylefeng.guns.modular.business.frequency.pricelibrary.model.result.PickTakePrice;
import cn.stylefeng.guns.modular.business.frequency.pricelibrary.model.result.PkgPriceLibrary;
import cn.stylefeng.guns.modular.business.frequency.pricelibrary.model.result.PkgPriceLibrarySearch;
import cn.stylefeng.guns.modular.business.frequency.pricelibrary.service.PriceLibraryService;
import cn.stylefeng.guns.modular.business.util.BusinessUtil;
import cn.stylefeng.guns.sys.modular.util.SnowIdUtils;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

/**
 * 价格库 服务实现类
 *
 * @author yujie
 * @date 2023/05/09 17:16
 */
@Slf4j
@Service
public class PriceLibraryServiceImpl extends ServiceImpl<PriceLibraryMapper, PriceLibrary> implements PriceLibraryService {

    @Autowired
    private CmAreaMapper cmAreaMapper;
    @Autowired
    private PriceLibraryMapper priceLibraryMapper;
    @Autowired
    private CmCityMapper cmCityMapper;
    @Autowired
    private BusinessUtil businessUtil;
    @Override
    public PageResult<PriceLibrary> page(PriceLibraryParam priceLibraryParam) {

        // 构造条件
        LambdaQueryWrapper<PriceLibrary> queryWrapper = new LambdaQueryWrapper<>();


        // 查询分页结果
        return new PageResult<>(this.page(PageFactory.defaultPage(), queryWrapper));
    }

    @Override
    public List<PriceLibrary> list(PriceLibraryParam priceLibraryParam) {

        // 构造条件
        LambdaQueryWrapper<PriceLibrary> queryWrapper = new LambdaQueryWrapper<>();


        return this.list(queryWrapper);
    }

    @Override
    public void add(PriceLibraryParam priceLibraryParam) {

        // 将dto转为实体
        PriceLibrary priceLibrary = new PriceLibrary();
        BeanUtil.copyProperties(priceLibraryParam, priceLibrary);


        this.save(priceLibrary);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(PriceLibraryParam priceLibraryParam) {

        // 根据id查询实体
        PriceLibrary priceLibrary = this.queryPriceLibrary(priceLibraryParam);
        // 更新实体
        this.updateById(priceLibrary);

    }

    @Override
    public void edit(PriceLibraryParam priceLibraryParam) {

        // 根据id查询实体
        PriceLibrary priceLibrary = this.queryPriceLibrary(priceLibraryParam);

        // 请求参数转化为实体
        BeanUtil.copyProperties(priceLibraryParam, priceLibrary);

        // 不能修改状态，用修改状态接口修改状态
        priceLibrary.setStatus(null);

        this.updateById(priceLibrary);
    }

    @Override
    public PriceLibrary detail(PriceLibraryParam priceLibraryParam) {
        return this.queryPriceLibrary(priceLibraryParam);
    }

    @Override
    public void changeStatus(PriceLibraryParam priceLibraryParam) {
        Long id = priceLibraryParam.getId();
        Integer status = priceLibraryParam.getStatus();


        // 更新枚举，更新只能更新未删除状态的
        LambdaUpdateWrapper<PriceLibrary> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper
            .eq(PriceLibrary::getId, id).set(PriceLibrary::getStatus, status);
        boolean update = this.update(updateWrapper);
        if (!update) {
            throw new ServiceException(StatusExceptionEnum.UPDATE_STATUS_ERROR);
        }
    }

    @Override
    public Page<PkgPriceLibrary> getPriceLibraryListPage(Page<Object> defaultPage, PriceLibraryDTO priceLibraryDTO,Long tenantId) {
        Page<PkgPriceLibrary> list = this.baseMapper.getPriceLibraryListPage(defaultPage, priceLibraryDTO,tenantId);
        if (list.getRecords().size() > 0) {
            for (PkgPriceLibrary pl : list.getRecords()) {
                // 城市所有的区
                pl.setStartAreaList(cmAreaMapper.getAreaListByCityCode(pl.getStartCode()));
                pl.setDestinationAreaList(cmAreaMapper.getAreaListByCityCode(pl.getDestinationCode()));
            }
        }
        return list;
    }

    @Override
    public boolean checkPriceLibraryAdd(PriceLibrary priceLibrary, StringBuilder errorMsg) {
        // 出发地、目的地、供应商、联系电话、成本 不可重复
        if (this.baseMapper.checkRepeat(null, priceLibrary.getStartCode(), priceLibrary.getDestinationCode(),
                priceLibrary.getCompanyName(), priceLibrary.getLinkPhone(), priceLibrary.getCost()) > 0) {
            errorMsg.append("已存在相同路线数据，请不要重复提交") ;
            return false;
        }
        priceLibrary.setId(SnowIdUtils.uniqueLong());
        priceLibrary.setCreateUser(LoginContextHolder.me().getSysLoginUserId());
        priceLibrary.setCheckUser(LoginContextHolder.me().getSysLoginUserId());
        priceLibrary.setCheckTime(new Date());
        priceLibrary.setTotalFee(priceLibrary.getCost().add(priceLibrary.getProfit() == null ? new BigDecimal("300") : priceLibrary.getProfit()));
        Long  tenantId = null;
        if (LoginContextHolder.me().isSuperAdmin()){
            tenantId = 1l;
        }else {
            tenantId = LoginContextHolder.me().getSysLoginUser().getTenantId();
        }
        priceLibrary.setTenantId(tenantId);
        return true;
    }

    @Override
    public void addLine(PriceLibrary priceLibrary) {
        // 待审核
        priceLibrary.setStatus(0);
        priceLibrary.setType(PriceLibraryTypeEnum.DISPATCHER_ADD.type);
        this.save(priceLibrary);
    }

    @Override
    public boolean checkPriceLibraryUpdate(PriceLibrary priceLibrary, StringBuilder errorMsg) {
        if (priceLibrary == null) {
            errorMsg.append("信息不能为空");
            return false;
        }
        if (priceLibrary==null) {
            errorMsg.append("价格库ID不能为空");
            return false;
        }
        if (this.baseMapper.checkRepeat(priceLibrary.getId(), priceLibrary.getStartCode(), priceLibrary.getDestinationCode(),
                priceLibrary.getCompanyName(), priceLibrary.getLinkPhone(), priceLibrary.getCost()) > 0) {
            errorMsg.append("已存在相同路线数据，请不要重复提交");
            return false;
        }
        priceLibrary.setTotalFee(priceLibrary.getCost().add(priceLibrary.getProfit() == null ? new BigDecimal("300") : priceLibrary.getProfit()));
        return true;
    }

    @Override
    public void lineUpdate(PriceLibrary priceLibrary) {
        priceLibrary.setStatus(PriceLibraryStatusEnum.WAIT_CHECK.status);
        this.baseMapper.updateById(priceLibrary);
    }

    @Override
    public void lineCheck(PriceLibrary priceLibrary) {
        priceLibrary.setStatus(PriceLibraryStatusEnum.COMMON.status);
        priceLibrary.setCheckTime(new Date());
        this.baseMapper.updateById(priceLibrary);
    }

    @Override
    public void disableOrStart(String id) {
        PriceLibrary pl = this.baseMapper.selectById(id);
        if (pl.getStatus() == 1) {
            //禁用
            this.baseMapper.updateStatusById(id, PriceLibraryStatusEnum.DISABLED.status, PriceLibraryStatusEnum.COMMON.status);
        } else {
            //启用
            this.baseMapper.updateStatusById(id, PriceLibraryStatusEnum.COMMON.status, PriceLibraryStatusEnum.DISABLED.status);
        }
    }

    @Override
    public List<PkgPriceLibrary> priceLibrarySearch(PriceLibraryDTO priceLibraryDTO,Long tenantId) {
        //PkgPriceLibrarySearchResult result = new PkgPriceLibrarySearchResult();
        List<PkgPriceLibrary> resultList = new ArrayList<>();
        priceLibraryDTO.setColumn("totalFee");
        priceLibraryDTO.setAsc(true);

        priceLibraryDTO.setStatus(PriceLibraryStatusEnum.COMMON.status);
        //获取价格库的列表
        Page<PkgPriceLibrary> zhidaList = this.baseMapper.getPriceLibraryListPage(PageFactory.defaultPage(1,9999), priceLibraryDTO,tenantId);
        if (zhidaList != null && zhidaList.getSize() > 0) {
            for (PkgPriceLibrary library : zhidaList.getRecords()) {
                library.setTransferId(library.getId().toString());
                library.setStartAreaList(cmAreaMapper.getAreaListByCityCode(library.getStartCode()));
                library.setDestinationAreaList(cmAreaMapper.getAreaListByCityCode(library.getDestinationCode()));
                library.setTransferCount("直达");
                resultList.add(library);
            }
        }
        //一次中转
        List<PkgPriceLibrarySearch> twiceList = this.baseMapper.getPriceLibrarySearchTwice(priceLibraryDTO);
        if (twiceList != null && twiceList.size() > 0) {
            for (PkgPriceLibrarySearch search : twiceList) {
                String transferId =SnowIdUtils.uniqueLongHex();
                PkgPriceLibrary library1 = this.baseMapper.getPriceDetail(search.getId1());
                PkgPriceLibrary library2 = this.baseMapper.getPriceDetail(search.getId2());
                // 和并项
                library1.setTransferCount("一次");
                library2.setTransferCount("一次");
                library1.setTransferId(transferId);
                library2.setTransferId(transferId);
                library1.setStartAreaList(cmAreaMapper.getAreaListByCityCode(library1.getStartCode()));
                library1.setDestinationAreaList(cmAreaMapper.getAreaListByCityCode(library2.getDestinationCode()));
                // 利润 合并后取第一段利润 + 100
                BigDecimal totalProfit = library1.getProfit().add(new BigDecimal("100"));
                library1.setProfit(totalProfit);
                library2.setProfit(totalProfit);
                // 参考报价
                BigDecimal totalCost = library1.getCost().add(library2.getCost());
                library1.setTotalFee(totalCost.add(totalProfit));
                library2.setTotalFee(totalCost.add(totalProfit));
                resultList.add(library1);
                resultList.add(library2);
                // 总利润，第一段利润 + 100
                //search.setTotalProfit(totalProfit);
                //search.setPriceLibraryList(plList);
                //提车费送车费
                //getPickTakeFee(search, priceLibraryDTO, originalStartCityCode, originalDestinationCityCode);
            }
        }
        //两次中转
        List<PkgPriceLibrarySearch> thriceList = this.baseMapper.getPriceLibrarySearchThrIce(priceLibraryDTO);
        if (thriceList != null && thriceList.size() > 0) {
            for (PkgPriceLibrarySearch search : thriceList) {
                String transferId = SnowIdUtils.uniqueLongHex();
                PkgPriceLibrary library1 = this.baseMapper.getPriceDetail(search.getId1());
                PkgPriceLibrary library2 = this.baseMapper.getPriceDetail(search.getId2());
                PkgPriceLibrary library3 = this.baseMapper.getPriceDetail(search.getId3());
                // 和并项
                library1.setTransferCount("两次");
                library2.setTransferCount("两次");
                library3.setTransferCount("两次");
                library1.setTransferId(transferId);
                library2.setTransferId(transferId);
                library3.setTransferId(transferId);
                library1.setStartAreaList(cmAreaMapper.getAreaListByCityCode(library1.getStartCode()));
                library1.setDestinationAreaList(cmAreaMapper.getAreaListByCityCode(library3.getDestinationCode()));
                // 利润 合并后取第一段利润 + 100
                BigDecimal totalProfit = library1.getProfit().add(new BigDecimal("100"));
                library1.setProfit(totalProfit);
                library2.setProfit(totalProfit);
                library3.setProfit(totalProfit);
                // 参考报价
                BigDecimal totalCost = library1.getCost().add(library2.getCost()).add(library3.getCost());
                library1.setTotalFee(totalCost.add(totalProfit));
                library2.setTotalFee(totalCost.add(totalProfit));
                library3.setTotalFee(totalCost.add(totalProfit));
                resultList.add(library1);
                resultList.add(library2);
                resultList.add(library3);
            }
        }
        //result.setTwiceList(twiceList);
        //result.setThriceList(thriceList);
        return resultList;
    }

    @Override
    public List<PriceLibrary> getExportDataList() {
        return this.baseMapper.getExportDataList();
    }

    @Override

    @Transactional(rollbackFor = Exception.class)
    public void importExcel(MultipartFile file) throws IOException {
        long startTime = System.currentTimeMillis();
        ExcelReader excelReader = null;
        InputStream in = null;
        try {
            in = file.getInputStream();
            excelReader = EasyExcel.read(in, PriceLibrary.class, new PriceLibraryListener(priceLibraryMapper, cmCityMapper)).build();
            ReadSheet readSheet = EasyExcel.readSheet(0).build();
            excelReader.read(readSheet);
        } catch (IOException e) {
            log.error("import excel to db fail", e);
        } finally {
            in.close();
            // 这里一定别忘记关闭，读的时候会创建临时文件，到时磁盘会崩
            if (excelReader != null) {
                excelReader.finish();
            }
        }

        long endTime = System.currentTimeMillis();
        long totalTime = endTime - startTime;
        log.info("【消耗时间为】{}", totalTime);
    }

    @Override
    public Page getPickTakePriceListPage(PriceLibraryDTO pickTakePriceDTO) {
        int total = priceLibraryMapper.countPickTakePriceList(pickTakePriceDTO);
        Page<PickTakePrice> page=new Page<>();
        if (total > 0) {
            page = priceLibraryMapper.getPickTakePriceListPage(PageFactory.defaultPage(), pickTakePriceDTO);
        }
        return page;
    }

    @Override
    public BigDecimal getPickFeeByAreaCode(PriceLibraryDTO pickTakePriceDTO) {
        return null;
    }

    @Override
    public BigDecimal getTakeFeeByAreaCode(PriceLibraryDTO pickTakePriceDTO) {
        return null;
    }
//
//    @Override
//    public void updatePickTakePrice(PickTakePrice pickTakePrice) {
//        pickTakePriceMapper.updateById(pickTakePrice);
//    }

    @Override
    public PkgPriceLibrary getMinimumPrice(PriceLibraryDTO priceLibraryDTO) {
        // 如果选择的是区，则取到市级code
        PkgPriceLibrary library = priceLibraryMapper.getMinimumPrice(priceLibraryDTO,businessUtil.getTenantId());
        // ----------------start------------
        List<Integer> result = new ArrayList<>();
        if (library != null) {
            result.add(library.getCost().add(library.getProfit()).intValue());
        }
        // 中转价格查询
        Long tenantId = businessUtil.getTenantId();
        List<PkgPriceLibrary> resultList = priceLibrarySearch(priceLibraryDTO,tenantId);
        if (resultList != null) {
            for (PkgPriceLibrary pkgPriceLibrary : resultList) {
                result.add(pkgPriceLibrary.getTotalFee().intValue());
            }
        }
        if (result.size() > 0) {
            PkgPriceLibrary ppl = new PkgPriceLibrary();
            ppl.setTotalFee(new BigDecimal(Collections.min(result)));
            return ppl;
        } else {
            return new PkgPriceLibrary();
        }
    }

    @Override
    public PkgPriceLibrary getDetailById(String id) {
        return baseMapper.getDetailById(id);
    }

    /**
     * 获取价格库
     *
     * @author yujie
     * @since 2023/05/09 17:16
     */
    private PriceLibrary queryPriceLibrary(PriceLibraryParam priceLibraryParam) {
        PriceLibrary priceLibrary = this.getById(priceLibraryParam.getId());
        if (ObjectUtil.isEmpty(priceLibrary)) {
            throw new ServiceException(PriceLibraryExceptionEnum.NOT_EXISTED);
        }
        return priceLibrary;
    }
}